#include <iostream>
#include <string>
#include <stdlib.h>
#include <stdint.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>

#include "gen-cpp/news_types.h"
#include "include/searcher.h"
#include "newsService.h"

#include <concurrency/PosixThreadFactory.h>
#include <concurrency/ThreadManager.h>
#include <protocol/TBinaryProtocol.h>
#include <server/TSimpleServer.h>
#include <server/TThreadPoolServer.h>
#include <server/TThreadedServer.h>
#include <server/TNonblockingServer.h> 
#include <transport/TServerSocket.h>
#include <transport/TBufferTransports.h>

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using namespace ::apache::thrift::concurrency;
using boost::shared_ptr;

using namespace std;

Searcher* searcher;

class newsServiceHandler : virtual public newsServiceIf {
 public:
  newsServiceHandler() {
    searcher = new Searcher();

  }
  void search(SearchResult& _return, const std::string& query, const int32_t show_num) {

    SRes* result = new SRes[show_num];
    int total_sum = searcher->search(query,show_num,result);
    int actual_show_num = std::min(total_sum, show_num);
    _return.total_sum = total_sum;
    _return.show_num = actual_show_num;
    for(int i = 0; i < actual_show_num; ++i) {
      ResultItem ri;
      ri.score = result[i].score;
      ri.title = result[i].title;
      ri.url = result[i].url;
      _return.show_result.push_back(ri);
    }

    delete []result;
  }
};

int main(int argc, char **argv) {

  /*
  shared_ptr<newsServiceHandler> handler(new newsServiceHandler());
  shared_ptr<TProcessor> processor(new newsServiceProcessor(handler));
  shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

  TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
  */

  const int port = 19091;
  const int workerCount = 2;
  shared_ptr<newsServiceHandler> handler(new newsServiceHandler());
  shared_ptr<TProcessor> processor(new newsServiceProcessor(handler));
  shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

  shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(workerCount);
  shared_ptr<PosixThreadFactory> threadFactory(new PosixThreadFactory());
  threadManager->threadFactory(threadFactory);
  threadManager->start();

  TThreadPoolServer server(processor, serverTransport, transportFactory, protocolFactory, threadManager);

  server.serve();

  delete searcher;
  return 0;
}

